package install

import (
	"fmt"
	"io/ioutil"
	"path"
	"strconv"
	"strings"
	"time"

	"gitee.com/shaddy/k3sinstall/mylog"
	"gopkg.in/yaml.v2"
)

type Install struct {
	Config *K3sConfig
}

func getIp(host string) string {
	return strings.Split(host, ":")[0]
}
func (c *Install) initSys() {
	mylog.Info.Println("开始初始化")
	c.Config.setHostName()
	c.Config.runCmdMasterAndNode(`systemctl stop firewalld && systemctl disable firewalld`)
	c.Config.runCmdMasterAndNode(`sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config && setenforce 0`)
	c.Config.runCmdMasterAndNode(`cat > /etc/resolv.conf << EOF
nameserver 8.8.8.8
EOF`)

}

func (c *Install) setup() {
	mylog.Info.Println("开始安装")
	c.Config.transFile(c.Config.PkgFile)
	c.Config.runCmdMasterAndNode(fmt.Sprintf("tar -xzvf %s", path.Join(c.Config.WorkDir, c.Config.PkgFile)))
	c.Config.runCmdMasterAndNode(fmt.Sprintf("echo \"%s  registry.hbfec.com\" >> /etc/hosts", getIp(c.Config.Masters[0])))
	c.Config.runCmdMasterAndNode(fmt.Sprintf("mkdir -p /var/lib/rancher/k3s/agent/images/ && cp %s /var/lib/rancher/k3s/agent/images/ && cp %s /usr/local/bin", path.Join(c.Config.WorkDir, "k3s", c.Config.ImgFile), path.Join(c.Config.WorkDir, "k3s", "k3s")))
	c.Config.runCmdMasterAndNode(fmt.Sprintf("mkdir -p /etc/rancher/k3s/ && cp %s /etc/rancher/k3s/", path.Join(c.Config.WorkDir, "k3s", "registries.yaml")))
	c.Config.runCmdForAllMasters(fmt.Sprintf("INSTALL_K3S_SELINUX_WARN=true sh %s", path.Join(c.Config.WorkDir, "k3s", "install.sh")))
	mytoken := synRunCmd(c.Config.Masters[0], c.Config.User, c.Config.Passwd, "cat /var/lib/rancher/k3s/server/node-token")
	if mytoken == "" {
		mylog.Error.Panic("安装时token获取失败")
	} else {
		mytoken = strings.Replace(mytoken, "\n", "", -1)
	}
	c.Config.runCmdForAllNodes(fmt.Sprintf("INSTALL_K3S_SELINUX_WARN=true K3S_URL=https://%s:6443 K3S_TOKEN=%s %s", getIp(c.Config.Masters[0]), mytoken, path.Join(c.Config.WorkDir, "k3s", "install.sh")))

}

func (c *Install) mysoft() {
	k3s := make(chan bool)
	go func() {
		for {
			mylog.Info.Println("等待k3s集群, 如果长时间等待，请联系管理员... ")
			n, _ := strconv.Atoi(strings.Replace(synRunCmd(c.Config.Masters[0], c.Config.User, c.Config.Passwd, "kubectl get nodes | grep Ready | wc -l"), "\n", "", -1))
			if n > 0 {
				k3s <- true
				break
			}
			time.Sleep(10000 * time.Millisecond)
		}
	}()
	<-k3s
	c.Config.runCmdForMaster0(fmt.Sprintf("ctr i import %s", path.Join(c.Config.WorkDir, "k3s", "registry.tar")))
	c.Config.runCmdForMaster0(fmt.Sprintf("kubectl create -f %s", path.Join(c.Config.WorkDir, "k3s", "config", "registry.sc.yaml")))
	c.Config.runCmdForMaster0(fmt.Sprintf("kubectl create -f %s", path.Join(c.Config.WorkDir, "k3s", "config", "registry.yaml")))
	c.Config.runCmdForMaster0(fmt.Sprintf("mkdir -p /var/lib/rancher/k3s/storage/pvc-registry-data && tar -xzf %s -C /var/lib/rancher/k3s/storage/pvc-registry-data", path.Join(c.Config.WorkDir, "k3s", "registry.data.gz")))
	c.Config.runCmdForMaster0(fmt.Sprintf("kubectl create -f %s", path.Join(c.Config.WorkDir, "k3s", "config", "buildkit.yaml")))
	c.Config.runCmdForMaster0(fmt.Sprintf("kubectl create -f %s", path.Join(c.Config.WorkDir, "k3s", "config", "package.yaml")))
	c.Config.runCmdForMaster0(fmt.Sprintf("kubectl create -f %s", path.Join(c.Config.WorkDir, "k3s", "kuboard-v3.yaml")))
	agent := make(chan bool)
	go func() {
		for {
			mylog.Info.Println("等待kuboard 安装 ， 如果长时间等待，请联系管理员... ")
			time.Sleep(10000 * time.Millisecond)
			n, _ := strconv.Atoi(strings.Replace(synRunCmd(c.Config.Masters[0], c.Config.User, c.Config.Passwd, "kubectl get pods -A | grep kuboard-agent | wc -l"), "\n", "", -1))
			if n > 0 {
				agent <- true
				break
			}
		}
	}()
	<-agent
	c.Config.runCmdForMaster0(`kubectl patch deploy/kuboard-agent -n kuboard -p '{"spec": {"template": {"spec": {"containers":[{"name": "kuboard-agent","imagePullPolicy": "IfNotPresent"}]}}}}'`)

}

func (c *Install) myhook() {
	c.Config.runCmdForMaster0(fmt.Sprintf("cd %s && sh hook.sh", path.Join(c.Config.WorkDir, "k3s")))
}

func InstallHook(config *K3sConfig) {
	mylog.Info.Println("开始进入初始化安装")

	install := &Install{
		Config: config,
	}
	//初始化系统
	install.initSys()

	//安装
	install.setup()
	//安装软件
	install.mysoft()

	context, err := yaml.Marshal(install.Config)
	if err != nil {
		mylog.Error.Fatalf("解析配置文件错误 err: %s", err.Error())
	}
	err = ioutil.WriteFile(install.Config.ConfigFile, context, 0777)
	if err != nil {
		mylog.Warning.Printf("写入配置文件错误 configfile: %s err: %s \n", install.Config.ConfigFile, err.Error())
	}

	install.myhook()

}
